import java.io.Serializable;
import java.util.Vector;

/**
 * Klasse die een vector klok implementeert.
 * 
 * @author Jelle Polders
 *
 */


public class VectorClock implements Comparable, Serializable {
	private static final long serialVersionUID = 7071843573153929708L;
	protected int processID;
	protected Vector<Integer> clock;
		
	/**
	 * Constructor
	 *
	 *	@param het processID
	 */
	public VectorClock() {
		clock = new Vector<Integer>();
		this.processID = -1;
	}
	
	public int size() {
		return clock.size();
	}
	
	public int getTimestamp(int processID) {
		if (clock != null && processID < size())
			return clock.get(processID);
		else
			return 0;
	}
	
	
	/**
	 * Updaten de klok
	 * 
	 * @param vc de meegegeven klok
	 */
	public synchronized void update(VectorClock vc){
		int size = size();
		if (size < vc.size()) {
			for (int i = size; i < vc.size(); i++)
				add(i, vc.getTimestamp(i));
		}
		for (int i = 0; i < size; i++)
			if (vc.getTimestamp(i) > getTimestamp(i)) {
				clock.add(i, vc.getTimestamp(i));
				clock.remove(i+1);
		}
	}
	
	public synchronized void add(int otherProcessID) {
		if (otherProcessID >= size())
			add(otherProcessID, 0);
	}
	/**
	 * Voeg nieuwe timestamp toe aan vector klok.
	 * 
	 * @param otherProcessID	process ID van het nieuwe/andere proces
	 * @param timestamp			timestamp van het nieuwe/andere proces
	 */
	public synchronized void add(int otherProcessID, int timestamp) {
		for (int i = clock.size(); i <= otherProcessID; i++)
			clock.add(0);
		
		clock.add(otherProcessID, timestamp);
		clock.remove(otherProcessID + 1);
	}

	/**
	 * 
	 */
	public synchronized void increment() {
		if (processID > -1) {
			clock.add(processID, clock.get(processID) + 1);
			clock.remove(processID + 1);
		}
	}

	/**
	 * Returned -1, 0, 1 als het meegegeven object respectievelijk kleiner, gelijk aan of groter is dan het object.
	 * 
	 * @return -1, 0, 1 als het meegegeven object respectievelijk kleiner, gelijk aan of groter is dan het object
	 */
	public int compareTo(Object vc) {
		VectorClock otherVC = (VectorClock) vc;
		int compare = 0;
		
		if (clock.size() != otherVC.clock.size())
			if (clock.size() > otherVC.clock.size())
				// deze klok is de nieuwste want hij bevat een process dat nog niet aanwezig is in de andere
				return -1; 
			else 
				// deze klok is ouder want de andere bevat een process dat nog niet aanwezig is op deze
				return 1;		
		else
			for (int i = 0; i < clock.size() && compare != 0; i++)
				compare = clock.get(i) - otherVC.clock.get(i);
		
		return compare;				
	}

	/**
	 * Returned de vector klok.
	 * 
	 * @return de vector klok
	 */
	public Vector<Integer> getClock() {
		return clock;
	}

	/**
	 * Zet de Vector klok.
	 * 
	 * @param clock de nieuwe vector klok
	 */
	public void setClock(Vector<Integer> clock) {
		this.clock = clock;
	}
	
	/**
	 * Returned het process ID.
	 * 
	 * @return het process ID
	 */
	public int getProcessID() {
		return processID;
	}

	/**
	 * Zet het nieuwe process ID. En voeg dit ook toe aan de vector clock.
	 * 
	 * @param processID het nieuwe process ID
	 */
	public void setProcessID(int processID) {
		this.processID = processID;
	}
	
	public void setProcessIDAndAdd(int processID) {
		this.processID = processID;
		if (processID >= 0)
			add(processID, 0);
	}

	/**
	 * Returned de timpestamp die bij uw process ID hoort.
	 * 
	 * @return de timestamp
	 */
	public int getTimestamp() {
		if (processID >= 0)
			return clock.get(processID);
		else
			return -1;
	}	
}
